﻿using System;
using System.Collections.Generic;
using UnityEngine;

namespace Jinndev {

    public static class EventManager {

        private static MultiMap<string, Action<EventData>> actions = new MultiMap<string, Action<EventData>>();

        public static void Add(Enum type, Action<EventData> action) {
            Add(type.ToString(), action);
        }

        public static void Add(string type, Action<EventData> action) {
            if (string.IsNullOrWhiteSpace(type)) {
                return;
            }
            actions.Add(type, action);
        }

        public static void Remove(Enum type, Action<EventData> action) {
            Remove(type.ToString(), action);
        }

        public static void Remove(string type, Action<EventData> action) {
            if (string.IsNullOrWhiteSpace(type)) {
                return;
            }
            actions.Remove(type, action);
        }

        public static void AutoSet(MonoBehaviour behaviour, Enum type, Action<EventData> action) {
            AutoSet(behaviour.gameObject, type.ToString(), action);
        }

        public static void AutoSet(MonoBehaviour behaviour, string type, Action<EventData> action) {
            AutoSet(behaviour.gameObject, type, action);
        }

        public static void AutoSet(GameObject gameObject, Enum type, Action<EventData> action) {
            AutoSet(gameObject, type.ToString(), action);
        }

        public static void AutoSet(GameObject gameObject, string type, Action<EventData> action) {
            if (string.IsNullOrWhiteSpace(type)) {
                return;
            }
            Add(type, action);
            DestroyCallback.Add(gameObject, () => {
                Remove(type, action);
            }, "RemoveEvent: " + type);
        }

        public static void ClearType(Enum type) {
            ClearType(type.ToString());
        }

        public static void ClearType(string type) {
            if (string.IsNullOrWhiteSpace(type)) {
                return;
            }
            actions.RemoveAll(type);
        }

        public static void Clear() {
            actions.Clear();
        }

        public static void Invoke(Enum type, params object[] args) {
            Invoke(type.ToString(), args);
        }

        public static void Invoke(string type, params object[] args) {
            if (string.IsNullOrWhiteSpace(type)) {
                return;
            }
            if (actions.TryGetValues(type, out List<Action<EventData>> list)) {
                foreach (Action<EventData> action in list) {
                    try {
                        action?.Invoke(new EventData(type, args));
                    }
                    catch (Exception e) {
                        Debug.LogException(e);
                    }
                }
            }
        }

    }

}
